#include <Arduino.h>
#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiUdp.h"
#include <Time.h>


/********************************用户可变配置********************************/

//WiFi相关配置
WiFiClient Tcp;                                                   // WiFi对象
const char* SSID = "ChinaNet-cXFv";                               // 替换为你的WiFi名称
const char* PASSWD = "tuggp2mg";                                  // 替换为你的WiFi密码

//UDP相关配置
WiFiUDP Udp;
unsigned int LocalPort = 2333;                                    // 替换为你的本地端口号
const char SendIP[] = "192.168.255.255";                          // UDP广播网段192.168.*.*
unsigned int SendPort = 8080;                                     // UDP广播到端口8080
String UdpBuffer = "";
String UdpSendBuffer = "";

//巴法云TCP配置
const char Bemfa_Host[] = "bemfa.com";                             // 服务器地址
const char Bemfa_Port[] = "8344";                                  // 服务器端口号
const String Bemfa_Key = "202b7b5004cf44538bc750dd1f1d7477";       // 巴法云私钥
const String Bemfa_Topic = "test009";                              // 巴法云订阅主题
struct Bemfa_CMD{                                                  // 用巴法云窗帘命令强行理解为多种命令,然后用小爱训练达到目的
  char POWERON[3] = "on";                                           // 开命令
  char SHUTDOWN[4] = "off";                                         // 关命令
  char RESTART[6] = "on#10";                                        // 重启命令
  char SLEEP[6] = "on#20";                                          // 睡眠命令
  char DORMANCY[6] = "on#30";                                       // 休眠命令
  char LOCK[6] = "on#40";                                           // 锁定命令
} BCMD;
unsigned long long int HeartBeat = 0;
unsigned long long int HeartBeatTime = 0;
time_t HeartLastBeatTime = 0;
unsigned int HeartBeatMaxTime = 30;                               // 心跳计时器最大值,60S
unsigned int MaxBuffer = 64;                                      // 缓冲区最大值
String BemfaBuffer = "";                                          // TCP获取的数据
String BemfaSendBuffer = "";
String BemfaTopic = "";
String BemfaMsg = "";

//电脑相关设置
char MAC[] = {0xd8,0x50,0xe6,0x3e,0x57,0xbb};                     // 电脑MAC地址
struct PCCMD{
  String POWERON = "POWERON";                                      // 开命令
  String SHUTDOWN = "SHUTDOWN";                                    // 关命令
  String RESTART = "RESTART";                                      // 重启命令
  String SLEEP = "SLEEP";                                          // 睡眠命令
  String DORMANCY = "DORMANCY";                                    // 休眠命令
  char GETSTATE[9] = "GETSTATE";                                   // 获取电脑状态
} PCMD;


/********************************用户不可变配置********************************/

void Bemfa_Init(void);
void Bemfa_HeartBeat(void);
void Bemfa_Active(void);
void WiFi_Init(void);
void WiFi_Keep(void);
void SendCMD(String CMD);
bool GetState(void);
String GetUdpData(void);
void GetBemfaData(void);
void MakeSendUdpPacket(String Msg);
void MakeSendTcpPacket(String Msg);
void HandleTcpMsg(void);


void setup() {
  Serial.begin(115200);
  WiFi_Init();
  Udp.begin(LocalPort);
  Bemfa_Init();
  Serial.println("初始化完成!");
}

void loop() {
  WiFi_Keep();
  Bemfa_HeartBeat();
//  Bemfa_Active();
  GetBemfaData();
  SendCMD(PCMD.POWERON);
  delay(1000);
  HeartBeatTime++;
}


void WiFi_Init(void){                                                   // WiFi初始化
  WiFi.begin(SSID, PASSWD);
  Serial.print("正在连接到WiFi: ");
  Serial.print(SSID);
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("已连接到WiFi: ");
  Serial.println(SSID);
  Serial.println("Local address: " + WiFi.localIP().toString());        // 打印本地地址
  Serial.println("Subnet mask: " + WiFi.subnetMask().toString());       // 打印掩码
  Serial.println("Gateway IP: " + WiFi.gatewayIP().toString());         // 打印网关IP
  Serial.println("DNS server IP: " + WiFi.dnsIP().toString());          // 打印DNS服务器IP
  Serial.println("MAC address: " + WiFi.macAddress());                  // 打印MAC地址
  Serial.println("RSSI: " + String(WiFi.RSSI()));                       // 打印信号强度
  Serial.println("Channel: " + String(WiFi.channel()));                 // 打印信道
//  Serial.println("Hostname: " + WiFi.hostname);                       // 打印主机名
  Serial.println("WiFi初始化成功!");
}

void WiFi_Keep(void){
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("WiFi已断开,正在尝试重新连接!");
    WiFi_Init();
  }
}

void Bemfa_Init(void){
  if(WiFi.status() == WL_CONNECTED){
    Tcp.connect(Bemfa_Host, atoi(Bemfa_Port));
    while(!Tcp.connected()){
      Serial.println("正在连接Bemfa服务器...");
      delay(500);
    }
    String TcpTemp = "cmd=1&uid=" + Bemfa_Key + "&topic=" + Bemfa_Topic + "\r\n";
    Tcp.print(TcpTemp);
    Tcp.flush();
    while(!Tcp.available());
    BemfaBuffer = "";
    while(Tcp.available()){
      char c = Tcp.read();
      BemfaBuffer += c;
    }
    if(BemfaBuffer)
      Serial.println("Bemfa服务器连接成功!");
      Serial.println(BemfaBuffer);
  }
}

void SendCMD(String CMD){
  Udp.beginPacket(SendIP, SendPort);
  int i,j;
  char cmd[] = CMD.c_str();
  for(i=sizeof(cmd); i>=j; j++)
    Udp.write(cmd[i]);
  Udp.endPacket();
}

bool GetState(void){
  SendCMD(PCMD.GETSTATE);
  delay(1000);
  GetUdpData();
  if(UdpBuffer == PCMD.POWERON)
  {
    return 1;
  }
  else if(UdpBuffer == PCMD.SHUTDOWN)
  {
    return 0;
  }
}

String GetUdpData(void){
  int UdpRecSize = Udp.parsePacket();
  if(UdpRecSize){
//    Udp.read(UdpBuffer, &UdpRecSize);
    for(int i = 0; i < UdpRecSize; i++)
      UdpBuffer[i] = Udp.read();
    UdpBuffer[UdpRecSize] = '\0';
    Serial.println(UdpBuffer);
  }
  else
  {
    UdpBuffer = "";
    return UdpBuffer;
  }
}

void MakeSendTcpPacket(String Msg)
{
  BemfaSendBuffer = "cmd=2&uid=" + Bemfa_Key + "&topic=" + Bemfa_Topic + "&msg=" + Msg + "\r\n" ;
}

void Bemfa_HeartBeat(void)
{
  Serial.print("HeartBeatTime: ");
  Serial.println(HeartBeatTime);
  Serial.print("HeartLastBeatTime: ");
  Serial.println(HeartLastBeatTime);
  Serial.print("HeartBeatMaxTime: ");
  Serial.println(HeartBeatMaxTime);
  Serial.print("HeartBeat: ");
  Serial.println(HeartBeat);
  if(HeartBeatTime - HeartLastBeatTime >= HeartBeatMaxTime)
  {
    HeartLastBeatTime = HeartBeatTime;
    if(GetState())
    {
      MakeSendTcpPacket(BCMD.POWERON);
      Tcp.print(BemfaSendBuffer);
      while(!Tcp.available());
      BemfaBuffer = "";
      while(Tcp.available()){
        char c = Tcp.read();
        BemfaBuffer += c;
      }
      Serial.println("DokiDoki!");
      HeartBeat++;
    }
    else{
      MakeSendTcpPacket(BCMD.POWERON);
      Tcp.print(BemfaSendBuffer);
      while(!Tcp.available());
      BemfaBuffer = "";
      while(Tcp.available()){
        char c = Tcp.read();
        BemfaBuffer += c;
      }
      Serial.println("DokiDoki!");
      HeartBeat++;
    }
    Tcp.flush();
    Serial.println(BemfaSendBuffer);
  }
}

void GetBemfaData(void)
{
  if(!Tcp.available());
  BemfaBuffer = "";
  if(Tcp.available()){
    char c = Tcp.read();
    BemfaBuffer += c;
    while(Tcp.available()){
      char c = Tcp.read();
      BemfaBuffer += c;
    }
    Serial.print("从Bemfa服务器获取到数据: ");
    Serial.println(BemfaBuffer);
    BemfaBuffer.trim();
    int topicIndex = BemfaBuffer.indexOf("&topic=")+7; //c语言字符串查找，查找&topic=位置，并移动7位，不懂的可百度c语言字符串查找
    int msgIndex = BemfaBuffer.indexOf("&msg=");//c语言字符串查找，查找&msg=位置
    BemfaTopic = BemfaBuffer.substring(topicIndex,msgIndex);//c语言字符串截取，截取到topic,不懂的可百度c语言字符串截取
    BemfaMsg = BemfaBuffer.substring(msgIndex+5);//c语言字符串截取，截取到消息
    Serial.print("Topic: ");
    Serial.println(BemfaTopic);
    Serial.print("Msg: ");
    Serial.println(BemfaMsg);
    delay(1000);
  }
}

void HandleTcpMsg(void)
{
  if(BemfaBuffer)
  {
    if(BemfaTopic == Bemfa_Topic)
    {
      if(BemfaMsg == BCMD.POWERON)
      {
        Serial.println("收到开机指令");
        SendCMD(PCMD.POWERON);
      }
      else if(BemfaMsg == BCMD.SHUTDOWN)
      {
        Serial.println("收到关机指令");
        SendCMD(PCMD.SHUTDOWN);
      }
    }
  }
  BemfaBuffer = "";
}
